﻿/*
   Copyright 2012 University of Southampton

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using uk.ac.soton.ses.DAL;
using System.Web;
using System.Linq;
using System.Security.Principal;

namespace uk.ac.soton.ses.UserControls
{
    public partial class ExperimentMetadataToolsUserControl : UserControl
    {
        private bool _isInitialised = false;
        private MaterialsMetadataContext _dbcontext = null;
        private int _experimentID;
        private ExperimentQuickSearch _searchControl_parametercopyfrom;
        private ExperimentQuickSearch _searchControl_parametercopyto;
        public EventHandler MetadataRebindRequired;
        private WindowsIdentity _currentUser = null;

        #region Page life cycle methods

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            this._currentUser = Context.User.Identity as WindowsIdentity;
            string idString = Page.Request.QueryString["ID"];
            if (int.TryParse(idString, out this._experimentID) && this._experimentID > 0)
            {
                this._dbcontext = HttpContext.Current.GetMaterialsDBContext();
                this.AddControls();
                this.ConfigureEvents();

                //Allow Page_Load to databind
                this._isInitialised = true;
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            //We only bind the first time and expect parent controls call DataBindAllControls when something has changed
            if (this._isInitialised && !Page.IsPostBack)
            {
                this.DataBindAllControls();
            }
        }

        #endregion

        #region Private methods

        public void DataBindAllControls()
        {
            //Bind the available templates
            this.DataBindParameterTemplates();
        }

        private void AddControls()
        {
            //Find the experiments quick search box (for copying parameters to this exp), cast it, and store it in a field
            this._searchControl_parametercopyfrom = this.Control_ExperimentQuickSearch_ParameterCopyFrom as ExperimentQuickSearch;

            //Find the experiments quick search box (for copying parameters to another exp), cast it, and store it in a field
            this._searchControl_parametercopyto = this.Control_ExperimentQuickSearch_ParameterCopyTo as ExperimentQuickSearch;

            //Set the new template name to something we know is unique
            this.TextBox_NewTemplateName.Text = DateTime.Now.ToString();
        }

        private void ConfigureEvents()
        {
            //Set up buttons
            this.btn_CreateNewTemplate.Click += new EventHandler(btn_CreateNewTemplate_Click);
            this.btn_CopyParameters.Click += new EventHandler(btn_CopyParameters_Click);

            //Handle experiment selected events
            this._searchControl_parametercopyfrom.ExperimentSelected += new ExperimentSelectedEventHandler(this.QuickSearchControl_ParameterCopyFrom_ExperimentSelected);
            this._searchControl_parametercopyto.ExperimentSelected += new ExperimentSelectedEventHandler(this.QuickSearchControl_ParameterCopyTo_ExperimentSelected);
        }

        #endregion

        #region Data binding

        /// <summary>
        /// Data binding parameter templates list
        /// </summary>
        private void DataBindParameterTemplates()
        {
            IQueryable<Experiment> templates =
                this._dbcontext.Experiments.Where(exp => exp.ID == this._experimentID)
                .SelectMany(exp => exp.ExperimentType.ExperimentTypeExperimentTemplateMaps)
                .Select(map => map.Experiment);

            list_ParameterTemplates.Items.Clear();

            foreach (Experiment exp in templates)
            {
                list_ParameterTemplates.Items.Add(new ListItem(string.Format("{0}:{1}", exp.ID, exp.Name), exp.ID.ToString()));
            }
        }

        #endregion

        #region Control Events

        private void QuickSearchControl_ParameterCopyFrom_ExperimentSelected(object sender, ExperimentSelectedEventArgs e)
        {
            try
            {
                this._dbcontext.CopyParametersBetweenExperiments(e.SelectedExperimentID, this._experimentID,false);
                this._dbcontext.SaveChanges();
                this.MetadataRebindRequired(this, new EventArgs());
            }
            catch (ExperimentAccessDeniedException)
            {
                HDCSharedWebFunctions.AddErrorLabel("Access denied to experiment " + e.SelectedExperimentID, this.CopyFromExperimentMessagePlaceHolder);
            }
        }

        private void QuickSearchControl_ParameterCopyTo_ExperimentSelected(object sender, ExperimentSelectedEventArgs e)
        {
            try
            {
                this._dbcontext.CopyParametersBetweenExperiments(this._experimentID, e.SelectedExperimentID,false);
                this._dbcontext.SaveChanges();
                this.MetadataRebindRequired(this, new EventArgs());
            }
            catch (ExperimentAccessDeniedException)
            {
                HDCSharedWebFunctions.AddErrorLabel("Access denied to experiment " + e.SelectedExperimentID, this.CopyToExperimentMessagePlaceHolder);
            }
        }


        /// <summary>
        /// Handles the click event, generated when CreateNewTemplate button is clicked
        /// </summary>
        /// <param name="sender">The control that generated the event</param>
        /// <param name="e">The event arguments</param>
        protected void btn_CreateNewTemplate_Click(object sender, EventArgs e)
        {
            try
            {
                Experiment templateExperiment = this._dbcontext.CreateTemplateFromExperiment(this._currentUser.User, this._experimentID, TextBox_NewTemplateName.Text, false);
                this._dbcontext.SaveChanges();
                HyperLink newExperimentLink = new HyperLink();
                newExperimentLink.Text = "Template Experiment Created " + templateExperiment.ID;
                newExperimentLink.Target = "_blank";
                newExperimentLink.NavigateUrl = HDCConfiguration.GetUrl_ExperimentDetails(templateExperiment.ID);
                this.CreateTemplateMessagePlaceHolder.Controls.Add(new LiteralControl("&nbsp;"));
                this.CreateTemplateMessagePlaceHolder.Controls.Add(newExperimentLink);
            }
            catch (Exception)
            {
                HDCSharedWebFunctions.AddErrorLabel("Could not create template with this name", this.CreateTemplateMessagePlaceHolder);
            }
        }

        /// <summary>
        /// Handles the click event, generated when the CopyParameters button is clicked
        /// </summary>
        /// <param name="sender">The control that generated the event</param>
        /// <param name="e">The event arguments</param>
        protected void btn_CopyParameters_Click(object sender, EventArgs e)
        {
            string selectedExperimentString = this.list_ParameterTemplates.SelectedValue;
            int selectedExperimentID = 0;
            if (int.TryParse(selectedExperimentString, out selectedExperimentID))
            {
                try
                {
                    this._dbcontext.CopyParametersBetweenExperiments(selectedExperimentID, this._experimentID,false);
                    this._dbcontext.SaveChanges();
                    this.MetadataRebindRequired(this, new EventArgs());
                }
                catch (ExperimentAccessDeniedException)
                {
                }
            }
        }

        #endregion
}
}
